1. /* sbstempl.h by K.Tsuru */
  2. // ver. 2.17
  3. /***************************************************************
  4. SN library
  5. Template classes of binary splitting method using recursive
  6. procedure for a series in a form
  7. B(0)...B(k-1)
  8. S_L = sum_{k=0}^{L-1} ------------- A_k
  9. C(0)...(k) .
  10. [reference]
  11. 1)E.A.Karatsuba
  12. "Fast evaluation of transcendental functions"
  13. Problems of Information Transmission 27, pp.339-360, 1992
  14. Problemy Peredachi Informatsii 27, pp.76-99, 1991 (in Russian)].
  15. 2)B.Haible and T.Papaniklaou
  16. "Fast multiprecision evaluation of series of rational numbers"
  17. 3)T.Migita, A.Amano, N.Asada and S.Fujino
  18. "Recursive reduction of series for multiple-precision evaluation
  19. and its application to Pi calculation" (in Japanese)
  20. IPSJ Journal Vol.40, pp.4193-4200(1999).
  21. ***************************************************************/
  22. #ifndef BINARY_SPLITTING_TEMPLATE_H
  23. #define BINARY_SPLITTING_TEMPLATE_H
  24. template <class BSType> class BinarySplitting {
  25. protected:
  26. bool isOk; // can use the values A,B,C // ver 2.18
  27. BSType A, B, C;
  28. long L, prec; // The value of 'L' can be obtained by "ulong L = SCalcInfo::upToTerm;". See below.
  29. public:
  30. // A virtual function which sets coefficients Ak, Bk and Ck.
  31. virtual void setABC(long k, BSType& a, BSType& b, BSType& c) = 0;
  32. // If precision = 0, it does not call roundOff().
  33. BinarySplitting(long upto, long precision) : isOk(false), L(upto), prec(precision) {
  34. SCalcInfo::upToTerm = (ulong)L;
  35. }
  36. void putTogether();
  37. virtual ~BinarySplitting(){}
  38. private:
  39. void recursive(long n0, long n1, BSType &a, BSType &b, BSType &c);
  40. void roundOff(BSType &a, BSType &b, BSType &c, long f);
  41. public:
  42. // If "inv == true" return C / A, else A / C.
  43. SDouble getValue(bool inv = false);
  44. bool isOK() const { return isOk; } // ver 2.18
  45. void getAC(BSType &a, BSType &c) {
  46. a = A; c = C;
  47. }
  48. BSType getA() const { return A; }
  49. BSType getB() const { return B; }
  50. BSType getC() const { return C; }
  51. };
  52. /****************
  53. * Implementation
  54. *****************/
  55. template <class BSType> void BinarySplitting<BSType>::putTogether() {
  56. recursive(0, L, A, B, C); isOk = true;
  57. }
  58. template <class BSType> void BinarySplitting<BSType>::
  59. recursive(long n0, long n1, BSType &a, BSType &b, BSType &c) {
  60. BSType rA, rB, rC;
  61. if(n1 - n0 == 1) { setABC(n0, a, b, c); return; }
  62. long midN = (n0 + n1) / 2;
  63. recursive(n0, midN, a, b, c); // recursive call left side
  64. recursive(midN, n1, rA, rB ,rC); // right side
  65. a = a * rC + b * rA; // A(2k) * C(2k+1) + B(2k) * A(2k+1)
  66. b *= rB; // B(2k) * B(2k+1)
  67. c *= rC; // C(2k) * C(2k+1)
  68. if(prec) {
  69. roundOff(a, b, c, prec); roundOff(rA, rB, rC, prec);
  70. }
  71. }
  72. template <class BSType> void BinarySplitting<BSType>::
  73. roundOff(BSType &a, BSType &b, BSType &c, long f) {
  74. /* ver 2.18
  75. if (a.RawSign() == a.UNDECIDED || b.RawSign() == b.UNDECIDED
  76. || c.RawSign() == c.UNDECIDED) return;
  77. */
  78. long m = (long)a.Head() - f;
  79. if (m > 0) a.FigureClear(0, (uint)m);
  80. m = (long)b.Head() - f;
  81. if (m > 0) b.FigureClear(0, (uint)m);
  82. m = (long)c.Head() - f;
  83. if (m > 0) c.FigureClear(0, (uint)m);
  84. }
  85. template <class BSType> SDouble BinarySplitting<BSType>::getValue(bool inv) {
  86. if (!isOk) putTogether(); // ver 2.18
  87. if (inv) return SDouble(C) / SDouble(A);
  88. return SDouble(A) / SDouble(C);
  89. }
  90. /***************************************************************
  91. in the case of B(k) = 1, e.g. e - 1 = 1/1! + 1/2! + 1/3! + ....
  92. See sdcbse.cpp
  93. This can be also used the radix conversion of desimal. Let R radix
  94. S_L =(A_0 . A_1 A_2 A_3...)_R^(-1)
  95. = A_0 + A_1/R + A_2/R^2 + A_3/R^3 + ...
  96. A_k
  97. = sum_{k=0}^{L-1} --------
  98. R^k .
  99. ****************************************************************/
  100. template <class BSType> class BinarySplittingA1C {
  101. protected:
  102. bool isOk; // can use the values A, C // ver 2.18
  103. BSType A, C;
  104. long L, prec; // The value of 'L' can be obtained by "ulong L = SCalcInfo::upToTerm;". See below.
  105. public:
  106. // A virtual function which sets coefficients Ak and Ck.
  107. virtual void setAC(long k, BSType& a, BSType& c) = 0;
  108. // If precision = 0, it does not call roundOff().
  109. BinarySplittingA1C(long upto, long precision) : isOk(false), L(upto), prec(precision) {
  110. SCalcInfo::upToTerm = (ulong)L;
  111. }
  112. void putTogether();
  113. virtual ~BinarySplittingA1C(){}
  114. private:
  115. void recursive(long n0, long n1, BSType &a, BSType &c);
  116. void roundOff(BSType &a, BSType &c, long f);
  117. public:
  118. // If "inv == true" return C / A, else A / C.
  119. SDouble getValue(bool inv = false);
  120. bool isOK() const { return isOk; } // ver 2.18
  121. void getAC(BSType &a, BSType &c) {
  122. a = A; c = C;
  123. }
  124. BSType getA() const { return A; }
  125. BSType getC() const { return C; }
  126. };
  127. /****************
  128. * Implementation
  129. *****************/
  130. template <class BSType> void BinarySplittingA1C<BSType>::putTogether() {
  131. recursive(0, L, A, C); isOk = true;
  132. }
  133. template <class BSType> void BinarySplittingA1C<BSType>::
  134. recursive(long n0, long n1, BSType &a, BSType &c) {
  135. BSType rA, rC;
  136. if(n1 - n0 == 1) { setAC(n0, a, c); return; }
  137. long midN = (n0 + n1) / 2;
  138. recursive(n0, midN, a, c); // recursive call left side
  139. recursive(midN, n1, rA, rC); // right side
  140. a = a * rC + rA; // A(2k) * C(2k+1) + A(2k+1)
  141. c *= rC; // C(2k) * C(2k+1)
  142. if(prec) {
  143. roundOff(a, c, prec); roundOff(rA, rC, prec);
  144. }
  145. }
  146. template <class BSType> void BinarySplittingA1C<BSType>::
  147. roundOff(BSType &a, BSType &c, long f) {
  148. // if (a.RawSign() == a.UNDECIDED || c.RawSign() == c.UNDECIDED) return; // ver 2.18
  149. long m = (long)a.Head() - f;
  150. if (m > 0) a.FigureClear(0, (uint)m);
  151. m = (long)c.Head() - f;
  152. if (m > 0) c.FigureClear(0, (uint)m);
  153. }
  154. template <class BSType> SDouble BinarySplittingA1C<BSType>::getValue(bool inv) {
  155. if (!isOk) putTogether(); // ver 2.18
  156. if (inv) return SDouble(C) / SDouble(A);
  157. return SDouble(A) / SDouble(C);
  158. }
  159. /**************************************************************************
  160. in the case of C(k) = 1, e.g. S_L = A_0 + A_1 * B_0 + A_2 * B_0 * B_1 + ...
  161. It can be used to evaluate a polynomial of SLong or SInteger.
  162. **************************************************************************/
  163. template <class BSType> class BinarySplittingPoly {
  164. protected:
  165. bool isOk; // can use the values A,B // ver 2.18
  166. BSType A, B;
  167. long L; // The value of 'L' can be obtained by "ulong L = SCalcInfo::upToTerm;". See below.
  168. public:
  169. // A virtual function sets coefficients Ak and Bk.
  170. virtual void setAB(long k, BSType& a, BSType& b) = 0;
  171. BinarySplittingPoly(long upto) : isOk(false), L(upto) {
  172. SCalcInfo::upToTerm = (ulong)L;
  173. }
  174. void putTogether();
  175. virtual ~BinarySplittingPoly(){}
  176. private:
  177. void recursive(long n0, long n1, BSType &a, BSType &b);
  178. public:
  179. bool isOK() const { return isOk; } // ver 2.18
  180. BSType getValue(); //It returns the value of A.
  181. BSType getB() const { return B; }
  182. };
  183. /****************
  184. * Implementation
  185. *****************/
  186. template <class BSType> void BinarySplittingPoly<BSType>::putTogether() {
  187. recursive(0, L, A, B); isOk = true;
  188. }
  189. template <class BSType> void BinarySplittingPoly<BSType>::
  190. recursive(long n0, long n1, BSType &a, BSType &b) {
  191. BSType rA, rB;
  192. if(n1 - n0 == 1) { setAB(n0, a, b); return; }
  193. long midN = (n0 + n1) / 2;
  194. recursive(n0, midN, a, b); // recursive call left side
  195. recursive(midN, n1, rA, rB); // right side
  196. a = a + b * rA; // A(2k) + B(2k) * A(2k+1)
  197. b *= rB; // B(2k) * B(2k+1)
  198. }
  199. template <class BSType> BSType BinarySplittingPoly<BSType>::getValue() {
  200. if (!isOk) putTogether(); // ver 2.18
  201. return A;
  202. }
  203. /***********************************************************************
  204. It evaluates exp(n/d) with BSType n and d using binary splitting method.
  205. There is a use example in "sdfexbsr.cpp".
  206. ************************************************************************/
  207. template <class BSType> class ExpBSRationalNumber
  208. : public BinarySplitting<BSType> {
  209. BSType num, den; // numerator and denominator
  210. public:
  211. ExpBSRationalNumber(long L, long prec,
  212. const BSType& n, const BSType& d)
  213. : BinarySplitting<BSType>(L, prec), num(n), den(d) {}
  214. void setABC(long k, BSType& a, BSType& b, BSType& c) {
  215. a.SetInt(1); b = num;
  216. if (k == 0) c.SetInt(1);
  217. else c = k * den;
  218. }
  219. };
  220. /*********************************************************************
  221. SFraction class is not used. When SFraction class is used, the speed becomes
  222. slower and the executable file size larger.
  223. **********************************************************************/
  224. struct SLFraction {
  225. SLong num, den;
  226. };
  227. struct SDFraction {
  228. SDouble num, den;
  229. };
  230. /*********************************************************************
  231. It splits a SDouble value X in the form of rational number series
  232. X = u_0 + u_1/v + u_2/v^2 + u_3/v^4 + u_4/v^8 + ... + u_p/v^(2^{p-1}).
  233. where v = S_BASE. It returns 'p'.
  234. Then we obtain
  235. exp(X) = exp(u_0)exp(u_1/v)exp(u_2/v^2)...
  236. Each term can be evaluated using binariy splitting method.
  237. **********************************************************************/
  238. int SplitSDouble(const SDouble& X, SNBlock <SLFraction>& slr, const SLong& V); // 3800
  239. #endif // BINARY_SPLITTING_TEMPLATE_H

sbstempl.h : last modifiled at 2017/11/06 15:03:25(9,374 bytes)
created at 2016/04/11 11:18:59
The creation time of this html file is 2017/11/06 15:07:45 (Mon Nov 06 15:07:45 2017).